package com.zj.ecology.utils;

import android.content.ContentResolver;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.AsyncTask;
import android.support.annotation.FloatRange;
import android.text.TextUtils;
import android.widget.ImageView;

import com.squareup.picasso.Picasso;
import com.zj.base.utils.DisplayUtils;
import com.zj.base.utils.ToastUtils;

import java.io.IOException;
import java.lang.ref.WeakReference;

import static com.squareup.picasso.MemoryPolicy.NO_CACHE;
import static com.squareup.picasso.MemoryPolicy.NO_STORE;

/**
 * Created by zhaojie on 2017/10/10.
 */

public class ImageLoaderUtils {
    private static Context context;
    private static boolean isInit = false;

    /**
     * initialize
     * 在BaseAppliCation调用进行初始化
     *
     * @param c
     */
    public static void initialize(Context c) {
        if (isInit)
            return;
        context = c;
        isInit = true;
    }

    public static ImageView load(ImageView iv, String url, int width, int height) {
        width = calculateOptions(width);
        height = calculateOptions(height);
        Picasso.with(context).load(TextUtils.isEmpty(url) ? "0" : url).centerCrop().resize(width, height).memoryPolicy(NO_CACHE, NO_STORE).into(iv);
        return iv;
    }

    public static ImageView loadWithCache(ImageView iv, String url, int width, int height) {
        width = calculateOptions(width);
        height = calculateOptions(height);
        Picasso.with(context).load(TextUtils.isEmpty(url) ? "0" : url).centerCrop().resize(width, height).into(iv);
        return iv;
    }

    public static ImageView load(ImageView iv, String url, int width, int height, int defaultBg) {
        width = calculateOptions(width);
        height = calculateOptions(height);
        Picasso.with(context).load(TextUtils.isEmpty(url) ? "0" : url).centerCrop().resize(width, height).memoryPolicy(NO_CACHE, NO_STORE).placeholder(defaultBg).error(defaultBg).into(iv);
        return iv;
    }

    public static ImageView loadWithCache(ImageView iv, String url, int width, int height, int defaultBg) {
        width = calculateOptions(width);
        height = calculateOptions(height);
        Picasso.with(context).load(TextUtils.isEmpty(url) ? "0" : url).centerCrop().resize(width, height).placeholder(defaultBg).error(defaultBg).into(iv);
        return iv;
    }

    public static ImageView loadLocalBitmap(ImageView iv, String uri, int w, int h) {
        int degree = readPicDegree(uri);
        Picasso.with(context).load(TextUtils.isEmpty(uri) ? "0" : uri).rotate(degree).centerCrop().resize(w, h).memoryPolicy(NO_CACHE, NO_STORE).into(iv);
        return iv;
    }

    /**
     * 通过ExifInterface类读取图片文件的被旋转角度
     * 解决系统将保存的图片自动旋转的问题
     *
     * @param path ： 图片文件的路径
     * @return 图片文件的被旋转角度
     */
    public static int readPicDegree(String path) {
        if (TextUtils.isEmpty(path)) return 0;
        int degree = 0;
        // 读取图片文件信息的类ExifInterface
        ExifInterface exif = null;
        try {
            exif = new ExifInterface(path);
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (exif != null) {
            int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
            if (orientation != -1) {
                switch (orientation) {
                    case ExifInterface.ORIENTATION_ROTATE_90:
                        degree = 90;
                        break;
                    case ExifInterface.ORIENTATION_ROTATE_180:
                        degree = 180;
                        break;
                    case ExifInterface.ORIENTATION_ROTATE_270:
                        degree = 270;
                        break;
                }
            }
        }
        return degree;
    }

    private static int calculateOptions(int ops) {
        return ops <= 0 ? 10 : ops;
    }

    public static Uri getUriById(Context context, int id) {
        Uri uri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
                + context.getResources().getResourcePackageName(id) + "/"
                + context.getResources().getResourceTypeName(id) + "/"
                + context.getResources().getResourceEntryName(id));
        return uri;
    }

    /**
     * 图片操作工厂类
     */
    public static BitmapBuilder factoryBitmap(Context context, Uri uri) {
        return new BitmapBuilder(context, uri);
    }

    public static class BitmapBuilder {

        private WeakReference<Context> wk_ctx;
        private Uri uri;
        private float scale = 0f;
        private float dpWidth = 0f, dpHeight = 0f;
        private int degree = 0;

        public BitmapBuilder(Context context, Uri uri) {
            this.uri = uri;
            this.wk_ctx = new WeakReference<>(context);
        }

        public BitmapBuilder scale(@FloatRange(from = 0.0f, to = 1.0f) float scale) {
            this.scale = scale;
            return this;
        }


        public BitmapBuilder crop(float dpWidth, float dpHeight) {
            this.dpWidth = Math.max(0f, dpWidth);
            this.dpHeight = Math.max(0f, dpHeight);
            return this;
        }

        public BitmapBuilder rotate(int degrees) {
            this.degree = degrees;
            return this;
        }

        public BitmapBuilder rotate() {
            this.degree = ImageLoaderUtils.readPicDegree(uri.getPath());
            return this;
        }

        public void excute(OnBitmapGotListener onBitmapGotListener) {
            if (wk_ctx == null || uri == null) {
                return;
            }
            new getBitmapByAsync(wk_ctx, uri, degree, onBitmapGotListener).execute(scale, dpWidth, dpHeight);
        }

        public static class getBitmapByAsync extends AsyncTask<Float, Integer, Bitmap> {

            private OnBitmapGotListener onBitmapGotListener;
            private Uri uri;
            private WeakReference<Context> context;
            private int degree;

            public getBitmapByAsync(WeakReference<Context> context, Uri uri, int degree, OnBitmapGotListener onBitmapGotListener) {
                this.context = context;
                this.uri = uri;
                this.degree = degree;
                this.onBitmapGotListener = onBitmapGotListener;
            }

            @Override
            protected Bitmap doInBackground(Float... floats) {
                if (floats.length != 3 || uri == null || context == null) return null;
                Bitmap bitmap = null;
                try {
                    bitmap = Picasso.with(context.get()).load(uri).rotate(degree).config(Bitmap.Config.ARGB_4444).memoryPolicy(NO_CACHE, NO_STORE).get();
                    if (bitmap == null) return null;
                    float scale = floats[0], dpWidth = floats[1], dpHeight = floats[2];
                    if (scale > 0) {
                        bitmap = scaleBitmap(bitmap, scale);
                    }
                    if (dpWidth > 0 && dpHeight > 0 && bitmap != null) {
                        bitmap = cropBitmap(bitmap, dpWidth, dpHeight);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (OutOfMemoryError error) {
                    ToastUtils.showSafeToast(context.get(), "请清理手机运行内存");
                }
                return bitmap;
            }

            @Override
            protected void onPostExecute(Bitmap bitmap) {
                if (onBitmapGotListener != null) onBitmapGotListener.onGet(bitmap);
            }

            @Override
            protected void onProgressUpdate(Integer... values) {
                if (onBitmapGotListener != null) onBitmapGotListener.onProgressChange(values[0]);
            }
        }
    }


    //将Drawable转为bitmap
    public static Bitmap drawableToBitmap(Drawable drawable, int w, int h, boolean isNeedClip) {
        int width = isNeedClip ? w : drawable.getIntrinsicWidth();   // 取 drawable 的长宽
        int height = isNeedClip ? h : drawable.getIntrinsicHeight();
        Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;         // 取 drawable 的颜色格式
        Bitmap bitmap = Bitmap.createBitmap(width, height, config);     // 建立对应 bitmap
        Canvas canvas = new Canvas(bitmap);         // 建立对应 bitmap 的画布
        drawable.setBounds(0, 0, width, height);
        drawable.draw(canvas);      // 把 drawable 内容画到画布中
        return bitmap;
    }

    public static Bitmap drawableToBitmap(Drawable drawable) {
        return drawableToBitmap(drawable, 0, 0, false);
    }

    //压缩drawable -> 依赖转换方法 drawableToBitmap（）；
    public static Drawable zoomDrawable(Drawable drawable, int w, int h, boolean needClip) {
        int width = drawable.getIntrinsicWidth();
        int height = drawable.getIntrinsicHeight();
        Bitmap oldbmp = null;
        if (needClip) oldbmp = drawableToBitmap(drawable, w, h, true);
        else oldbmp = drawableToBitmap(drawable); // drawable 转换成 bitmap
        Matrix matrix = new Matrix();   // 创建操作图片用的 Matrix 对象
        float scaleWidth = ((float) w / width);   // 计算缩放比例
        float scaleHeight = ((float) h / height);
        matrix.postScale(scaleWidth, scaleHeight);         // 设置缩放比例
        Bitmap newbmp = Bitmap.createBitmap(oldbmp, 0, 0, width, height, matrix, true);       // 建立新的 bitmap ，其内容是对原 bitmap 的缩放后的图
        oldbmp.recycle();
        return new BitmapDrawable(newbmp);       // 把 bitmap 转换成 drawable 并返回
    }

    /**
     * 旋转图片
     *
     * @param angle  被旋转角度
     * @param bitmap 图片
     * @return 旋转后的图片
     */
    public static Bitmap rotaingImageView(int angle, Bitmap bitmap) {
        Bitmap returnBm = null;
        // 根据旋转角度，生成旋转矩阵
        Matrix matrix = new Matrix();
        matrix.postRotate(angle);
        try {
            // 将原始图片按照旋转矩阵进行旋转，并得到新的图片
            returnBm = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
            if (returnBm == null) {
                returnBm = bitmap;
            }
            return returnBm;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bitmap != returnBm) {
                bitmap.recycle();
            }
        }
        return null;
    }


    /**
     * 按照某个取值为0-1之间的比例缩放位图；
     *
     * @param bitmap 原图
     * @param scale  0.0f -1.0f
     * @return 缩放后的图像
     */
    public static Bitmap scaleBitmap(Bitmap bitmap, @FloatRange(from = 0.0f, to = 1.0f) float scale) {
        if (bitmap == null) {
            return null;
        }
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        Matrix matrix = new Matrix();
        matrix.preScale(scale, scale);
        Bitmap newBmp = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false);
        if (newBmp.equals(bitmap)) {
            return newBmp;
        }
        bitmap.recycle();
        return newBmp;
    }


    /**
     * 裁剪,按当前显示dp等比裁剪
     *
     * @param bitmap   原图
     * @param dpWidth  以dp为单位的横向裁剪宽度
     * @param dpHeight 以dp为单位的纵向裁剪高度
     * @return 裁剪后的图像
     */
    public static Bitmap cropBitmap(Bitmap bitmap, float dpWidth, float dpHeight) {
        int size[] = DisplayUtils.getDefaultDisplayMetrics();
        float screenWidth = size[0];
        float screenHeight = size[1];
        float width = DisplayUtils.dip2px(dpWidth);
        float height = DisplayUtils.dip2px(dpHeight);
        float scaleWidth = width / screenWidth;
        float scaleHeight = height / screenHeight;
        if (scaleWidth >= 1f || scaleHeight >= 1f) {
            return bitmap;
        }
        float b_w = bitmap.getWidth(); // 得到图片的宽，高
        float b_h = bitmap.getHeight();
        int bitmapCropWidth = (int) (scaleWidth * b_w + 0.5f);
        int bitmapCropHeight = (int) (scaleHeight * b_h + 0.5f);
        int startX = (int) ((b_w - bitmapCropWidth) / 2f);
        int startY = (int) ((b_h - bitmapCropHeight) / 2f);
        Bitmap result = Bitmap.createBitmap(bitmap, startX, startY, bitmapCropWidth, bitmapCropHeight);
        if (result.equals(bitmap)) {
            return result;
        }
        bitmap.recycle();
        return result;
    }

    public static abstract class OnBitmapGotListener {
        public abstract void onGet(Bitmap bitmap);

        public void onProgressChange(int progress) {

        }
    }

    public static abstract class OnBitmapSaveListener {

        public abstract void onChange(Bitmap bitmap);

        public void onProgressChange(int progress) {

        }
    }
}
